perm filename SERVO.OLD[CMS,LCS]3 blob sn#426287 filedate 1979-03-20 generic text, type T, neo UTF8
00100		TITLE SERVO
00200		.INSERT ASMBL.FAI[CMS,LCS]
00300	
00500	;I/O address definitions.
00600	   DAC ← 100000	;8 bit DAC.
00700	   JCR ← 120000	;Joint control output register.
00800	   ENCL ← 140000	;Encoder mux low.
00900	   ENCH ← 140001	;Encoder mux high.
01000	
01100	   STKSIZ ← 377	;Stack size.
01200	   LSBENB ← 40	;Enable LSB servo.
01300	
01400	;Zero page variables.
01500	;Not shared.
01600	
01800	DSPAT:	BLOCK 2	;Dispatch address for commands.
01900	DEFCMD:	0	;Deferred command.
02000	SAVPOS:	BLOCK 2	;Position for deferred servo command.
02100	
02200	CMDVEL:	BLOCK 2	;Commanded velocity.
02300	CURVEL:	BLOCK 2	;Current velocity.
02400		0	;SETPT-1.
02500	SETPT:	BLOCK 2	;Current setpoint.
02600		0	;SETINC-1.
02700	SETINC:	BLOCK 2	;Interpolating increment for setpoints.
02800	OLDSP:	BLOCK 2	;Last commanded setpoint, for CMDVEL.
02900	POSERR:	BLOCK 2	;Current position error.
03000	DACSIG:	BLOCK 2	;Scratch.
03100	
03200	INCTR:	0	;Count the interpolations.
03300	HSTTMR:	0	;Count ticks between host commands.
03400	
03500	LOGTMP:	BLOCK 4	;Temp for the arithmetic routines.
03600	
03700	ZAPEND ← .-1	;Clear all the above in startup.
03800	
03900	CURPOS:	BLOCK 2	;Current position, extended to 2 bytes.
04000	
04100	TL:	0	;Scratch for grey to binary.
04200	TH:	0
04300	
04400	FTMP:	BLOCK 2	;Copy of friction coefficient for multiply.
     

00100	;Shared ram.
00200	   LOC 200	;Second half of zero page.
00300	
00400		0	;Locked.
00500	STATUS:	0	;Flags for the host.
00600	
00700		0	;Locked.
00800	MODE:	0	;Mode bits from host.
00900	
01000	CKWORD:	BLOCK 2	;Host I/O check/command word.
01100	CMDPOS:	BLOCK 2	;Commanded position from host.
01200	
01225		0	;Locked.
01250	IOCTRL:	0	;Copy of JCR output port.
01275	
01300	;NINTER = function of INTSCL?
01400		0	;Locked.
01500	NINTER:	0	;# of interpolations between position
01600			;commands.
01700		0	;Locked.
01800	INTSCL:	0	;# of bits to shift setpoint dif for
01900			;interpolating.
02000		0	;Locked.
02100	HSTLIM:	0	;# of clock ticks allowed between host
02200			;commands.
02300	FRICTN:	BLOCK 2	;Viscous damping coefficient.
02400	GRAVTY:	BLOCK 2	;DC offset for gravity.
02500	POSTOL:	BLOCK 2	;Half-width of position tolerance band.
02600	INTTOL:	BLOCK 2	;Half-width of integration band.
02700	
02800	
02900	;Start of prom.
03000	   LOC 174000
03100	
03200	INITBL:	STATUS	↔	200
03300		MODE	↔	0
03400	
03500		NINTER	↔	=32
03600		INTSCL	↔	5
03700	
03800		HSTLIM	↔	=48
03900	
04000		377	;End of INITBL flag.
     

00100	;Power on and restart reset.
00200	START:	CLD
00300		LDXI	STKSIZ	;Setup stack.
00400		TXS
00500	
00600		LDAI	0
00700		LDXI	ZAPEND
00800	RLOOP:	STAZX	0	;Reset ram.
00900		DEX
01000		BPL	RLOOP
01100		STA	DAC	;Clear DAC.
01200	
01300		LDXI	370	;-8.
01400	ZSR:	STAZX	FRICTN+10	;Clear shared ram.
01500		INX
01600		BMI	ZSR
01700	
01800		TAY
01900		BEQ	RSTDEF	;Jump
02000	
02100	
02200	DLOOP:	INY
02300		LDAY	INITBL	;Init ram.
02400		STAZX	0
02500		INY
02600	
02700	RSTDEF:	LDXY	INITBL
02800		CPXI	377
02900		BNE	DLOOP
03000	
03100	STOP:	SEI	;Disable interrupts and stop?
03200		JSR	GETPOS	;Read encoder and convert to binary.
03400	
03500		JSR	SETPOS	;Set position and stop.
03600	
03700		CLI	;End of reset.
     

00100	RSTCKW:	LDAI	0	;Reset check word.
00200		SEI
00300		STAZ	CKWORD
00400		STAZ	CKWORD+1
00500		CLI
00600	;Idle loop. Wait for command.
00700	IDLE:	LDAZ	CKWORD+1;Check for new check word.
00800		BEQ	IDLE	;Not equal if bit 7 is 2's comp. of low byte?
00900	
01000		CLC
01100		SEI
01200		ADCZ	CKWORD
01300		LDXZ	CKWORD+1
01400		CLI
01500		TAY
01600		BNE	STOP	;Check word error.
01700	   ;Check here for immediate or deferred.
01800		LDAZ	DEFCMD	;Check if no TICK?
01900		BNE	STOP
02000	
02100		SEI
02200		LDAZ	CMDPOS	;Read position for servo command.
02300		LDYZ	CMDPOS+1
02400		CLI
02500	
02600		STAZ	SAVPOS	;Save it for later.
02700		STYZ	SAVPOS+1
02800	
02900		STXZ	DEFCMD	;Save deferred command.
03000	
03100		BNE	RSTCKW	;Done. Jump and handshake with CKWORD.
03200	
03300	;If HSTTMR or CKWORD or ? then stop?
03400	;Check notebook and add stop? etc.
03600	;Check GPOSER and in servo formula for sign reverse?
     

00100	;Deferred commands.
00150	;Put this routine on page 10-2.
00200	CMDSRV:	LDAZ	MODE	;Servo command.
00300		ANDI	202	;Test for servo enabled.
00400		CMPI	200
00500		BEQ	ENBLD
00600		JMP	CMDEND	;No. End this command. 
00700	
00800	ENBLD:	LDAZ	SAVPOS	;Enabled.
00900		LDXZ	SAVPOS+1;Get position.
01000		STAZ	DACSIG
01100		STXZ	DACSIG+1
01200		SEC
01300		SBCZ	SETPT
01400		STAZ	SETINC
01500		TXA
01600		SBCZ	SETPT+1
01700		LDXI	0
01800		STXZ	SETPT-1
01900		STXZ	SETINC-1
02000		LDXZ	INTSCL
02100	
02200	SCAL:	CMPI	200	;Extend sign.
02300		RORA
02400		RORZ	SETINC
02500		RORZ	SETINC-1
02600		DEX
02700		BNE	SCAL
02800	
02900		STAZ	SETINC+1
03000		LDAZ	NINTER
03100		STAZ	INCTR
03200		SEC
03300		LDAZ	DACSIG
03400		SBCZ	OLDSP
03500		STAZ	CMDVEL
03600		LDAZ	DACSIG+1
03700		SBCZ	OLDSP+1
03800		STAZ	CMDVEL+1
03900		LDAZ	DACSIG
04000		STAZ	OLDSP
04100		LDAZ	DACSIG+1
04200		STAZ	OLDSP+1
04300	
04400		LDAZ	IOCTRL
04500		ORAI	44	;Turn on servo and current mode enable bits.
04600		STAZ	IOCTRL
04700		STA	JCR	;Output it.
04800		LDAZ	HSTLIM	;Reset host timer.
04900		STAZ	HSTTMR
05000		JMP	CMDEND
     

00100	;Clock tick interrupt.
00200	TICK:	PHA	;Save state.
00300		TXA
00400		PHA
00500		TYA
00600		PHA
00700	
00750		JSR	GETPOS	;Read position and convert to binary.
00770	
00790	;Position conversion routine.
00795	;Put this routine on page 10-3.
00800	GETPOS:	LDY	ENCL	;Read encoder.
00900		LDA	ENCH
01000	
01100	;Convert from grey to binary.
01200		STAZ	TH
01300		LSRA	;Shift by 1.
01400		EORZ	TH
01500		STAZ	TH
01600		TAX	;X ← high byte.
01700	
01800		TYA
01900		STAZ	TL
02000		RORA
02100		EORZ	TL
02200		STAZ	TL
02300	
02400		LSRZ	TH	;Shift by 2.
02500		RORA
02600		LSRZ	TH
02700		RORA
02800	
02900		EORZ	TL
03000		STAZ	TL
03100		TAY	;Y ← low byte.
03200		TXA
03300		EORZ	TH
03400		STAZ	TH
03500	
03600		LSRA	;Shift by 4.
03700		RORZ	TL
03800		LSRA
03900		RORZ	TL
04000		LSRA
04100		RORZ	TL
04200		LSRA
04300		RORZ	TL
04400	
04500		EORZ	TH
04600		STAZ	TH
04700		TYA
04800		EORZ	TL
04900		EORZ	TH	;Shift by 8.
05000	;Returns converted position in A (low) and TH (high).
05100		RTS
     

00100		TAY	;Save low byte of binary position.
00200		LDXZ	TH	;Get high byte.
00300		SEC
00400		SBCZ	CURPOS	;Subtract the old position
00500		STAZ	CURVEL	;yielding the velocity.
00600		TXA	;High byte of binary position.
00700		SBCZ	CURPOS+1
00800		STAZ	CURVEL
00900	
01000		STYZ	CURPOS	;Set the current position.
01100		STXZ	CURPOS+1
01200	
01300		DECZ	HSTTMR	;Count the ticks since the last command
01400		BPL	HOSTOK	;and check for timeout.
01500	
01600		LDAI	0	;Host dead. Stop.
01700		STAZ	HSTTMR
01800		STAZ	CMDVEL
01900		STAZ	CMDVEL+1
02000	
02100	HOSTOK:	LDAI	4
02200		BITZ	IOCTRL	;If position mode is off,
02300		BNE	INTRS
02400		JMP	CURSRV	;don't servo.
02500	
02600	;Interpolate the setpoints.
02700	INTRS:	CLC
02800		LDAZ	SETPT-1
02900		ADCZ	SETINC-1;Add the increment to the setpoint.
03000		STAZ	SETPT-1
03100		LDAZ	SETPT
03200		ADCZ	SETINC
03300		STAZ	SETPT
03400		LDAZ	SETPT+1
03500		ADCZ	SETINC+1
03600		STAZ	SETPT+1
03700	
03800		DECZ	INCTR	;Check if this is the last interpolation.
03900		BNE	GPOSER
04000	
04100		LDAI	0	;Clear SETINC if done interpolating.
04200		STAZ	SETINC-1
04300		STAZ	SETINC
04400		STAZ	SETINC+1
04500	
04600	;Calculate the position error.
04700	GPOSER:	SEC
04800		LDAZ	CURPOS	;POSERR ← CURPOS - SETPT.
04900		SBCZ	SETPT
05000		STAZ	POSERR
05100		LDAZ	CURPOS+1
05200		SBCZ	SETPT+1
05300		STAZ	POSERR+1
     

00100		BITZ	MODE	;If servo is disabled, we're
00200		BPL	OOTOL	;automatically out of tolerance
00300	
00400		LDAZ	POSERR+1;Test the sign of pos error.
00500		BMI	NEGPER
00600	
00700		SEI
00800		LDAZ	POSTOL	;Positive. Compare with tol.
00900		CMPZ	POSERR
01000		LDAZ	POSTOL+1
01100		CLI
01200		SBCZ	POSERR+1
01300		BCS	TOLOK	;In tolerance.
01400		BCC	OOTOL	;Jump.
01500	
01600	NEGPER:	CLC	;Negative. Add the tolerance.
01700		SEI
01800		LDAZ	POSTOL
01900		ADCZ	POSERR
02000		LDAZ	POSTOL+1
02100		CLI
02200		ADCZ	POSERR+1
02300		BCS	TOLOK	;In tolerance.
02400	
02500	OOTOL:	LDAZ	IOCTRL	;Out of tolerance.
02600		ANDI	177	;Turn off the in tolerance
02700		BNE	WCNTRL	;indicator.
02800	
02900	TOLOK:	LDAZ	IOCTRL	;In tolerance. Turn it on.
03000		ORAI	200
03100	WCNTRL:	STAZ	IOCTRL
03200		STA	JCR	;Copy it to output.
03300	
03350	;Delete from here to end of page if no integrator?
03400		BITZ	MODE	;If intergration is disabled,
03500		BVC	OOBAND	;turn it off.
03600		LDAZ	POSERR+1;Test sign of position error.
03700		BMI	ADTOL
03800	
03900		SEI
04000		LDAZ	INTTOL	;Positive. Compare with tol.
04100		CMPZ	POSERR
04200		LDAZ	INTTOL+1
04300		CLI
04400		SBCZ	POSERR+1
04500		BCS	INBAND	;In band. Turn on integrator.
04600		BCC	OOBAND	;Jump.
04700	
04800	ADTOL:	CLC	;Negative. Add the tolerance.
04900		SEI
05000		LDAZ	INTTOL
05100		ADCZ	POSERR
05200		LDAZ	INTTOL+1
05300		CLI
05400		ADCZ	POSERR+1
05500		BCS	INBAND	;Check if in band.
05600	
05700	OOBAND:	LDAZ	IOCTRL	;Out of band. Turn off
05800		ORAI	10	;integration by setting the
05900		ANDI	357	;control bit. LSB servo off.
06000		BNE	WCTRL2	;Jump.
     

00050	;Delete from here to WCTRL2 if no LSB servo?
00100	INBAND:	LDAI	LSBENB	;In band. Is LSB servo enabled?
00200		BITZ	MODE
00300		BEQ	RCNTRL
00400	
00500		LDAZ	POSERR	;Yes. Is the error exactly 0?
00600		ORAZ	POSERR+1
00700		BNE	RCNTRL
00800	
00900		LDAZ	IOCTRL	;It is. Integration off, LSB
01000		ORAI	30	;servo on.
01100		BNE	WCTRL2	;Jump.
01200	
01300	RCNTRL:	LDAZ	IOCTRL	;LSB disabled or error
01400		ANDI	347	;not zero. LSB servo off,
01500				;integration on.
01600	
01700	WCTRL2:	STAZ	IOCTRL
01800		STA	JCR	;Output it.
01900	
02000		LDYZ	CURVEL	;Get the velocity,
02100		LDAZ	CURVEL+1
02200		JSR	LOG
02300	
02400		SEI
02500		LDXZ	FRICTN	;(Copy friction for multiply.)
02600		STXZ	FTMP
02700		LDXZ	FRICTN+1
02800		CLI
02900		STXZ	FTMP+1
03000		LDXI	FTMP	;multiply by the friction
03100		JSR	MULTIP	;coefficient,
03200		JSR	EXP
03300	
03400		TAX	;Save high byte.
03500		TYA	;Get low byte.
03600		CLC	;add the position error...
03700		ADCZ	POSERR
03800		STAZ	DACSIG
03900		TXA
04000		ADCZ	POSERR+1
04100		STAZ	DACSIG+1
04600	
04700		CLC	;...and the gravity offset.
04800		LDAZ	DACSIG
04900		SEI
05000		ADCZ	GRAVTY
05100		TAY	;Save low byte.
05200		LDAZ	GRAVTY+1
05300		CLI
05400		ADCZ	DACSIG+1
05600	
05700		JSR	PUTDAC	;Put result out to the DAC.
     

00100	CMDSP:	LDAZ	DEFCMD	;Check for a command.
00200		BEQ	INTXIT
00300	
00400		ANDI	2	;Low nibble command bit.
00500		TAX
00600		LDAX	CMDTBL	;Get command address.
00700		STAZ	DSPAT
00800		LDAX	CMDTBL+1
00900		STAZ	DSPAT+1
01000	
01100		JMPIN	DSPAT	;Execute command.
01200	
01300	CMDEND:	LDAI	0	;Done with deferred command.
01400		STAZ	DEFCMD	;Reset command word.
01500	
01600	INTXIT:	PLA	;Restore state and dismiss interrupt.
01700		TAY
01800		PLA
01900		TAX
02000		PLA
02100		RTI
02200	
02300	CURSRV:	LDAI	0	;Not servoing ("Current mode")...
02400		STAZ	SETPT-1	;Make the setpoint track
02500		LDAZ	CURPOS	;the current position in order to
02600		STAZ	SETPT	;keep the arm from twitching when
02700		LDAZ	CURPOS+1;the host enables the servo.
02800		STAZ	SETPT+1
02900		JMP	CMDSP	;Go check on commands.
03000	
03100	CMDTBL:		;DEFERRED COMMAND TABLE.
03200		CMDEND∧377	;Nop.
03300		(CMDEND⊗-10)∧377
03400	
03500		CMDSRV∧377	;Servo command.
03600		(CMDSRV⊗-10)∧377
     

00050	;Not a subroutine? Put this routine on page 3-1?
00100	;Set position subroutine.
00200	;Enter with position in A (low) and X (high).
00300	;Sets current position to that value, puts the setpoint
00400	;to the same, clears the setpoint interpolating
00500	;increment, and goes into stop mode?
00600	SETPOS:	STAZ	CURPOS	;Set the current position.
00700		STXZ	CURPOS+1
00800	
00900		STAZ	SETPT	;Set the position command.
01000		STXZ	SETPT+1
01100		STAZ	OLDSP
01200		STXZ	OLDSP+1
01300	
01400		LDAI	75	;I/O control bits for servo
01500		STAZ	IOCTRL	;enable on, all others off.
01600		STA	JCR
01700	
01800		LDAI	0
01900		STAZ	SETPT-1	;Clear the setpoint extension,
02000		STAZ	SETINC-1;the interpolator,
02100		STAZ	SETINC
02200		STAZ	SETINC+1
02300		STAZ	CMDVEL	;and the commanded velocity.
02400		STAZ	CMDVEL+1
02500	
02600		LDAZ	SETPT	;Return the regs. unchanged.
02700		RTS
02800	
02900	;DAC output subroutine.
03000	;Enter with 2 byte value in Y (low), A (high).
03100	;Clobbers all registers, but the 8 bits the
03200	;DAC got are returned in A.
03300	PUTDAC:	BMI	NEGDAC	;Assuming the last inst. loaded A.
03400		CPYI	200	;Positive. Compare with 2↑7.
03700		SBCI	0
03800		BCC	INRNGE
03900	
04000	TOOHI:	LDYI	177	;Too high. Saturate positive.
04100		BNE	INRNGE	;Jump.
04200	
04300	NEGDAC:	CPYI	200	;Negative. Compare with -2↑7.
04700		SBCI	377
04800		BCS	INRNGE
04900	
05000	TOOLOW:	LDYI	200	;Too low. Saturate to -2↑7.
05100	
05200	INRNGE:	LDAY	VETBL	;Straighting it.
05300		STA	DAC	;Output 8 bits to the DAC.
05400		RTS
     

00100	;Arithmetic routines.
00200	;Enter with high byte in A, low in Y.
00300	;Returns A = characteristic and sign, Y = mantissa.
00400	;Clobbers X, LOGTMP, LOGTMP+1.
00500	LOG:	STYZ	LOGTMP	;Save the inputs.
00600		STAZ	LOGTMP+1
00700	
00800		LDXI	20+100	;?Init characteristic to 15.
00900		CMPI	0	;Test sign of input.
01000		BPL	POSIN
01100		SEC	;Negative. 2's complement it.
01200		LDAI	0
01300		SBCZ	LOGTMP
01400		STAZ	LOGTMP
01500		LDAI	0
01600		SBCZ	LOGTMP+1
01700	POSIN:	BNE	NORML	;Is high byte zero?
01800		LDAZ	LOGTMP	;Yes. Low byte?
01900		BEQ	RTRN	;If so, return zero.
02000		LDYI	0	;Low nonzero. Shift left one
02100		STYZ	LOGTMP	;byte,
02200		LDXI	10+100	;change characteristic to 7.
02300	NORML:	DEX	;Normalize the number, counting the
02400		ASLZ	LOGTMP	;characteristic down. When the
02500		ROLA	;first "1" shifts out, we've subtracted
02600		BCC	NORML	;1 from the normalized number
02700		ASLZ	LOGTMP	;(This rounds the result)
02800		ADCI	=11	;and are left with the fraction
02900		TAY	;Adding 11 to that is equivalent to
03000		TXA	;adding 0.043.
03100		ADCI	0	;Propagate the carry into the
03200				;characteristic.
03300		ASLA	;Insert the sign bit from the saved
03400		ASLZ	LOGTMP+1;input.
03500		RORA
03600	RTRN:	RTS	;Done.
03700	
03800	;Enter with sign and characteristic in A, mantissa in Y
03900	;Returns 16-bit integer, low byte in Y, high in A.
04000	;Clobbers X, LOGTMP, LOGTMP+1.
04100	EXP:	STAZ	LOGTMP+1;Save sign of input.
04200		ANDI	177	;Mask it off.
04300		BEQ	ZEROIN	;Zero characteristic returns
04400		TAX	;zero.
04500		TYA	;Get the mantissa...
04600		SEC
04700		SBCI	=11	;...subtract 0.043...
04800		STAZ	LOGTMP	;(save this value)
04900		TXA	;...propagate the carry and get rid
05000		SBCI	100	;of the XS-64 offset.
05100		BMI	NEGIN	;If negative (value < 1.0)
05200				;return zero.
05300		CMPI	=15	;Test for overflow (value>=2↑15
05400		BCS	SATUR
05500		TAX	;...no. Number is in range.
05600		ADCI	370	;Is characteristic below 8?
05700		BMI	BLOATE
05800		TAX	;No. Reduce if by 8,
05900		JSR	UNNORM	;unnormalize.
06000		BMI	GETTMP	;Jump.
     

00100	BLOATE:	JSR	UNNORM	;Yes. Unnormalize, then
00200		ASLZ	LOGTMP	;(round result)
00300		ADCI	0
00400		STAZ	LOGTMP	;use result as low byte and
00500		LDAI	0	;set high byte to zero.
00600	
00700	GETTMP:	LDYZ	LOGTMP
00800	GTMP1:	LDXZ	LOGTMP+1;Test sign of input...
00900		BPL	POSIGN
01000		STAZ	LOGTMP+1;...negative. 2's complement
01100		LDAI	0	;the result.
01200		SEC
01300		SBCZ	LOGTMP
01400		TAY
01500		LDAI	0
01600		SBCZ	LOGTMP+1
01700	POSIGN:	RTS
01800	
01900	NEGIN:	LDAI	0	;Set the result to zero if the
02000	ZEROIN:	TAY	;input is negative.
02100		RTS
02200	
02300	SATUR:	LDYI	377	;Saturate result to 2↑15 - 1 if
02400		STYZ	LOGTMP	;input was 15 or more.
02500		LDAI	177
02600		BNE	GTMP1	;Jump.
02700	
02800	UNNORM:	LDAI	1	;Unnormalize subroutine. Add 1
02900		BNE	DECRX	;to the fraction.
03000	
03100	SCALE:	ASLZ	LOGTMP	;Scale the fraction left by the
03200		ROLA	;amount of the characteristic.
03300	DECRX:	DEX
03400		BPL	SCALE
03500		RTS
03600	
03700	;Enter with characteristic of multiplier in A,
03800	;mantissa in Y, X pointing to a pair of base page
03900	;locations containing the multiplicand (mantissa in the
04000	;low byte).
04100	;Returns the product in A and Y, same form as the
04200	;multiplier. Leaves X unchanged. Clobbers LOGTMP and
04300	;LOGTMP+1.
04400	MULTIP:	PHA
04500		EORZX	1	;Compute sign of result,
04600		STAZ	LOGTMP+1	;save it away.
04700		PLA
04800		ANDI	177	;Mask off multiplier sign.
04900		BEQ	ZEROIN	;If zero, return zero.
05000		STAZ	LOGTMP
05100		TYA	;Add the two logarithms.
05200		CLC
05300		ADCZX	0
05400		TAY
05500		LDAZX	1
05600		ANDI	177	;If multiplicand is zero,
05700		BEQ	ZEROIN	;return a zero.
05800		ADCZ	LOGTMP
05900		SEC
06000		SBCI	100	;Correct the XS-64 offset.
     

00100		BPL	INSIGN	;Result in range?
00200		ANDI	100	;No. If underflow,
00300		BNE	NEGIN	;return zero.
00400		LDAI	177	;Overflow. Saturate to
00500		LDYI	377	;highest magnitude.
00600	
00700	INSIGN:	ASLA	;Insert the sign of the result.
00800		ASLZ	LOGTMP+1
00900		RORA
01000		RTS
01100	
01200	;Inverse function: 2's complement the magnitude part
01300	;of a 15-bit logarithm.
01400	;Enter with characteristic in A, mantissa in Y.
01500	;Returns inverse in the same form. X unchanged.
01600	;Clobbers LOGTMP and LOGTMP+1.
01700	INV:	STYZ	LOGTMP	;Pretty straightforward...
01800		STAZ	LOGTMP+1
01900		SEC
02000		LDAI	0	;Complement the number by
02100		SBCZ	LOGTMP	;subtracting it from zero.
02200		TAY
02300		LDAI	0
02400		SBCZ	LOGTMP+1
02500		JMP	INSIGN	;Insert the original sign.
02600	
02700	;DAC output table.
02800	   LOC (.∨377)+1	;For start of next page.
02900	VETBL:		;DAC output table.
03000	N ← 0
03100	REPEATE 256,{N ↔ N←N+1 ↔}
03200	
03300	   NMI ← START	;Reset??
03400	;Interrupt vectors.
03500	   LOC 177772
03600		NMI∧377
03700		(NMI⊗-10)∧377
03800		START∧377
03900		(START⊗-10)∧377
04000		TICK∧377
04100		(TICK⊗-10)∧377
04200	END